package com.hoshiicloud.mallshop.service.impl.aftersale;

import com.alibaba.fastjson.JSONObject;
import com.hoshiicloud.common.constant.enumeration.Channel;
import com.hoshiicloud.common.constant.refund.RefundOrderStatusEnum;
import com.hoshiicloud.common.constant.refund.RefundServiceTypeEnum;
import com.hoshiicloud.common.exception.ServiceException;
import com.hoshiicloud.common.rpc.Response;
import com.hoshiicloud.common.utils.SignUtil;
import com.hoshiicloud.mallshop.dto.ConsulationMsgDto;
import com.hoshiicloud.mallshop.dto.RefundRbmqJsonDto;
import com.hoshiicloud.mallshop.feign.ShopPayMentFeignService;
import com.hoshiicloud.mallshop.feign.ShopSaleOrderFeignService;
import com.hoshiicloud.mallshop.feign.ShopUserFeignService;
import com.hoshiicloud.mallshop.param.UpdateRefundInfoParam;
import com.hoshiicloud.mallshop.service.aftersale.RefundManageService;
import com.hoshiicloud.payment.Paylist;
import com.hoshiicloud.payment.param.RefundRequest;
import com.hoshiicloud.payment.vo.RefundResponse;
import com.hoshiicloud.saleorder.entity.*;
import com.hoshiicloud.user.entity.company.Member;
import com.hoshiicloud.user.entity.store.PlatStore;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

/**
 * @author qry
 * @date 2019/9/4 15:14
 */
@Service
@Slf4j
public class RefundManageServiceImpl implements RefundManageService {

    @Autowired
    private ShopSaleOrderFeignService shopSaleOrderFeignService;

    @Autowired
    private ShopUserFeignService shopUserFeignService;

    @Autowired
    private ShopPayMentFeignService shopPayMentFeignService;

    @Override
    public Boolean updateRefundInfo(UpdateRefundInfoParam param) {
        //获取退款单信息
        RefundOrder ro = this.getRefundOrderResponse(param.getId());

        //获取下单店铺信息
        PlatStore platStore = this.getPlatStoreResponse(ro.getStoreId());

        //获取主订单信息
        OrderMain orderMain = this.getOrderMain(ro.getMainId());

        //生成协商历史的 提示数据
        ConsulationMsgDto cMsg = new ConsulationMsgDto();
        this.getConsulationsMsg(cMsg,ro,param,platStore,orderMain.getShippingId());

        //获取子订单信息
        OrderInfo orderInfo = this.getOrderInfo(ro.getSubId());

        //如果是付款按钮 获取原支付流水记录 并生成协商劣势的 退款提示数据
        this.getSucessRemark(param.getStatus(),orderInfo.getPayOrderId(),cMsg,ro.getRefundAmount());

        //商家操作协商历史 提示数据 生成Map
        Map<String, Object> map1 = this.generateRefundConsulationMap(platStore, cMsg);

        //系统协商历史 提示数据 生成Map
        Map<String, Object> map2 = this.generateSysConsulationMap(cMsg);

        //  生成商家协商历史对象   1 子订单id  2 退款单id  3 退款单状态  4 map
        Consultations c1 = this.generatorConsulations(ro.getSubId(), ro.getId(),param.getStatus(), map1);

        //  生成系统协商历史对象   1 子订单id  2 退款单id  3 退款单状态  4 map
        Consultations c2 = this.generatorConsulations(ro.getSubId(), ro.getId(),RefundOrderStatusEnum.SYS_RECORD.getCode(), map2);
        if(param.getStatus() == RefundOrderStatusEnum.REFUND_SUCCESS.getCode()) {
            //检查支付单存不存在
            Payorder payorder = this.checkPayIsExitst(orderInfo.getPayOrderId());

            //透传数据  队列处理
            RefundRbmqJsonDto attach = new RefundRbmqJsonDto();
            attach.setOrderInfoId(orderInfo.getId());
            attach.setOrderInfoQty(orderInfo.getQuantity().intValue());
            attach.setOrderMainId(orderMain.getId());
            attach.setOrderMainOrderStatus(orderMain.getOrderStatus());
            attach.setRefundServiceType(ro.getServiceType());
            attach.setC1(c1);
            attach.setC2(c2);
            attach.setRefundOrderUpParam(param);
            attach.setRefundId(param.getId());
            attach.setExtSkuId(orderInfo.getSkuId());
            attach.setRefundQty(ro.getApplyQtys());
            attach.setStoreId(orderInfo.getStoreId());
            String attachJson = JSONObject.toJSONString(attach);

            //调用退款接口  入参 ：平台ID ，支付单ID ，退款金额 ，退款原因，退款单id，支付的单总金额
            //调用退款接口后   剩余的业务在消息队列处理 （即消息中退款成功才处理 其他的更新状态等业务）
            this.payRefundToBuyer(orderMain.getPlatformId(),payorder.getPayListId(),
                    ro.getRefundAmount(),ro.getReasons(),ro.getId(),payorder.getPayAmount(),attachJson);

            UpdateRefundInfoParam param2 = new UpdateRefundInfoParam();
            param2.setId(param.getId());
            param2.setStatus(RefundOrderStatusEnum.BANK_PROCESSING.getCode());
            this.updateRefundOrderStatue(param2);
        }else {
            this.insertConsulations(c1);
            this.deleteSysConsulation(param.getId());
            this.insertConsulations(c2);
            this.updateRefundOrderStatue(param);
        }
        return true;
    }

    /**
     * 入参 ：平台ID ，支付订ID ，退款金额 ，退款原因，退款单id，支付的单总金额
     **/
    private void payRefundToBuyer(Long platFormId,Long payListId,BigDecimal refundAmount,String refundReason,
                                  Long refundId,BigDecimal oldPayOrderTotalAmount,String attachJson){
        RefundRequest refundRequest = RefundRequest.builder()
                .orderId(payListId) //订单号,即paylist主键
                .merId(platFormId) //商户号 这里取平台id
                .merOrderId(refundId.toString())  //支付流水的商户订单号 这里为 //退款单id
                .refundAmount((refundAmount.multiply(new BigDecimal(100))).intValue()) // 要退的金额
                .refundDesc(refundReason)    //退款原因
                .refundNo(refundId.toString()) //退款单id
                .totalAmount((oldPayOrderTotalAmount.multiply(new BigDecimal(100))).intValue())   //订单总金额,单位为分  oldPayOrderTotalAM
                .attach(attachJson) //透传JSON
                .build();
        log.error("lessee调用payment退款请求打印:"+JSONObject.toJSONString(refundRequest));
        TreeMap<String, String> map = null;
        try {
            map = SignUtil.objectToMap(refundRequest);
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException("退款失败,请联系客服");
        }
        String sign = SignUtil.sign(map, SignUtil.SIGN_SECRECT_KEY);
        refundRequest.setSign(sign);
        Response<RefundResponse> response = shopPayMentFeignService.refundOrder(refundRequest);
        log.error("lessee调用payment退款返回打印:"+JSONObject.toJSONString(response));
        if(null == response || response.getCode() !=200 || null == response.getData() ){
            if(null != response && response.getCode() !=200 && StringUtils.isNotBlank(response.getMsg())){
                throw new ServiceException("退款失败,"+response.getMsg());
            }
            throw new ServiceException("退款失败");
        }
    }


    private Payorder checkPayIsExitst(Long payOrderId) {
        Response<Payorder> rs = shopSaleOrderFeignService.queryPayorderById(payOrderId);
        if(null == rs || rs.getCode() != 200 || null == rs.getData()){
            throw new ServiceException("支付单不存在");
        }
        return rs.getData();
    }


    private void getSucessRemark(int status, Long payOrderId, ConsulationMsgDto cMsg, BigDecimal refundMoney) {
        if(status == RefundOrderStatusEnum.REFUND_SUCCESS.getCode()) {
            Paylist payList = this.getPaylist(payOrderId);
            if(Channel.WEIXIN.getChannel() == payList.getChannel()){
                cMsg.setRemark(refundMoney + "元已退回到" + Channel.getNameByChannel(payList.getChannel())
                     +"," + "0金币已退回买家的金币账户");
            }else{
                cMsg.setRemark(refundMoney + "元已退回到" + Channel.getNameByChannel(payList.getChannel())
                        + "(" + payList.getOutAccount() + ")," + "0金币已退回买家的金币账户");
            }

        }
    }

    private OrderInfo getOrderInfo(Long orderInfoId) {
        Response<OrderInfo> orderInfoRs = shopSaleOrderFeignService.getOrderInfoById(orderInfoId);
        if (null == orderInfoRs || orderInfoRs.getCode() != 200 || null == orderInfoRs.getData()) {
            throw new ServiceException("获取子订单信息失败");
        }
        return orderInfoRs.getData();
    }

    private Map<String, Object> generateSysConsulationMap(ConsulationMsgDto cMsg) {
        Map<String, Object> map2 = new HashMap<>();
        map2.put("avatar", "");
        map2.put("nickName", "好获严选系统");
        map2.put("realName", "");
        map2.put("title", cMsg.getSysTitle());
        map2.put("msg", cMsg.getSysMsg());
        map2.put("userType", 2);
        return map2;
    }

    private Map<String, Object> generateRefundConsulationMap(PlatStore platStore, ConsulationMsgDto cMsg) {
        Map<String, Object> map1 = new HashMap<>();
        map1.put("avatar", platStore.getFaceImages());
        map1.put("nickName", platStore.getStoreName());
        map1.put("realName", "");
        map1.put("userType",1);
        map1.put("title", cMsg.getTitle());
        map1.put("remark", cMsg.getRemark());
        map1.put("address", cMsg.getAddress());
        map1.put("receiveName", cMsg.getReceiveName());
        map1.put("receivePhone", cMsg.getReceivePhone());
        return map1;
    }

    public void deleteSysConsulation(Long refundId) {
        Response<Boolean> consultationsDeleteRs = shopSaleOrderFeignService.deletePhysicConsultations(refundId);
        if (null == consultationsDeleteRs || consultationsDeleteRs.getCode() != 200 || null == consultationsDeleteRs.getData()) {
            throw new ServiceException("删除退款单协商历史系统记录失败");
        }
    }


    private Paylist getPaylist(Long payOrderId) {
        Response<Paylist> payListRs = shopPayMentFeignService.getPaylistByPayOrderId(payOrderId.toString());
        if (null == payListRs || payListRs.getCode() != 200 || null == payListRs.getData()) {
            throw new ServiceException("获取原支付流水失败");
        }
        return payListRs.getData();
    }
    private Member getMemberResponse(Long memBerId) {
        Response<Member> memberRs = shopUserFeignService.getMembersById(memBerId);
        if (null == memberRs || 200 != memberRs.getCode() || null == memberRs.getData()) {
            throw new ServiceException("获取下单人信息失败");
        }
        return memberRs.getData();
    }

    /**
     *  1 子订单id  2 退款单id  3 退款单状态  4 map
     **/
    private Consultations generatorConsulations(Long orderInfoId, Long refundId,int status ,Map<String, Object> map1) {
        Consultations c = new Consultations();
        c.setSubId(orderInfoId);
        c.setRefundId(refundId);
        c.setStatus(status);
        c.setRemark(JSONObject.toJSONString(map1));
        return c;
    }
    public void insertConsulations(Consultations c){
        Response<Consultations> consultationsRs = shopSaleOrderFeignService.saveConsultations(c);
        if (null == consultationsRs || consultationsRs.getCode() != 200 || null == consultationsRs.getData()) {
            throw new ServiceException("新增退款单协商历史失败");
        }
    }


    public void updateRefundOrderStatue(UpdateRefundInfoParam param) {
        RefundOrder entity = new RefundOrder();
        entity.setId(param.getId());
        entity.setStatus(param.getStatus());
        Response<Boolean> rs = shopSaleOrderFeignService.updateRefundOrderById(entity);
        if (null == rs || rs.getCode() != 200) {
            throw new ServiceException("更新退款单状态失败");
        }
    }

    private OrderMain getOrderMain(Long mainId) {
        Response<OrderMain> orderMainRs = shopSaleOrderFeignService.getOrderMainById(mainId);
        if (null == orderMainRs || orderMainRs.getCode() != 200 || null == orderMainRs.getData()) {
            throw new ServiceException("获取主订单信息失败");
        }
        return orderMainRs.getData();
    }

    private PlatStore getPlatStoreResponse(Long storeId) {
        Response<PlatStore> platStoreRs = shopUserFeignService.getPlatStoreById(storeId);
        if (null == platStoreRs || platStoreRs.getCode() != 200 || null == platStoreRs.getData()) {
            throw new ServiceException("获取店铺信息失败");
        }
        return platStoreRs.getData();
    }

    private RefundOrder getRefundOrderResponse(Long refundId) {
        Response<RefundOrder> refundOrderRs = shopSaleOrderFeignService.getRefundOrderById(refundId);
        if (null == refundOrderRs || refundOrderRs.getCode() != 200 || null == refundOrderRs.getData()) {
            throw new ServiceException("获取退款单信息失败");
        }
        return refundOrderRs.getData();
    }

    private void getConsulationsMsg(ConsulationMsgDto cMsg,RefundOrder ro,UpdateRefundInfoParam param,PlatStore platStore,Integer mainShippId){
        if (param.getStatus() == RefundOrderStatusEnum.WAIT_SELLER_PAY.getCode()
                && ro.getServiceType() == RefundServiceTypeEnum.ONLY_REFUND.getCode()) {
            cMsg.setTitle("商家同意买家的退款请求");
            cMsg.setSysTitle("等待商家打款");
            cMsg.setSysMsg("请商家于3日内将款项退回至原支付方");
        } else if (param.getStatus() == RefundOrderStatusEnum.REFUND_CANCEL.getCode()) {
            cMsg.setTitle("买家取消了退款申请");
            cMsg.setSysTitle("退款已取消");
        } else if (param.getStatus() == RefundOrderStatusEnum.SELLER_REFUSE_REFUND.getCode()) {
            Member member = getMemberResponse(ro.getUserId());
            cMsg.setTitle("商家拒绝买家的退款请求");
            cMsg.setRemark("拒绝原因："+param.getRemark());
            cMsg.setSysTitle("商家拒绝退款");
            cMsg.setSysMsg("希望商家和买家协商一致，以免发生不必要的交易纠纷，买家昵称：" + member.getNickName()
                    + "，手机号码：" +member.getPhone());
        } else if (param.getStatus() == RefundOrderStatusEnum.WAIT_BUYER_DELIVERY.getCode()) {
            cMsg.setTitle("商家同意买家的退款请求");
            cMsg.setAddress(platStore.getAddress());
            cMsg.setReceiveName(platStore.getCharge());
            cMsg.setReceivePhone(platStore.getChargeTelphone());
            cMsg.setSysTitle("等待买家发货");
            cMsg.setSysMsg("您可以点击下方“提醒”按钮，通知买家发货");
        }else if (param.getStatus() == RefundOrderStatusEnum.WAIT_SELLER_PAY.getCode()
                && ro.getServiceType() == RefundServiceTypeEnum.REFUND_RETURN_GOODS.getCode()) {
            cMsg.setTitle("商家已确认收货");
            cMsg.setSysTitle("等待商家打款");
            cMsg.setSysMsg("请商家于3日内将款项退回至原支付方");
        }else if (param.getStatus() == RefundOrderStatusEnum.WAIT_SELLER_RECEIVE.getCode()
                &&  mainShippId == 3
                && ro.getServiceType() == RefundServiceTypeEnum.REFUND_RETURN_GOODS.getCode()) {
            cMsg.setTitle("商家同意买家的退款请求");
            cMsg.setSysTitle("等待商家确认收货");
            cMsg.setSysMsg("商家超过3日未确认收货，系统将自动确认收货");
        } else  if (param.getStatus() == RefundOrderStatusEnum.REFUND_SUCCESS.getCode()) {
            cMsg.setTitle("商家已完成退款");
            cMsg.setSysTitle("退款成功");
        }
    }
}
